import base64
import hashlib
import hmac

__version__ = "2.0.1"
__author__ = "ArtLinty"

# MIT License
#
# Copyright (c) 2019 立师兄Linty
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

"""
# Usage：
# call build_driver() for web browser instance
# call build_request() for web api instance
"""

from base.box import BoxDriver
from base.box import BoxRequest
from base.helper import CsvHelper, PathHelper, DbHelper, YamlHelper, JsonHelper
from base.infra import Logger

"""
main portal, for web browser driver
"""


def build_driver(url, driver_type, wait_seconds=None):
    """
    get driver for web browser testing
    :param wait_seconds:
    :param url: str，访问浏览器的 url
    :param driver_type: str，指定浏览器的类型，忽略大小写
        : c, chrome
        : i, ie
        : f, firefox
        : o, opera
        : s, safari
        : h, headless, headless_chrome, hc
    :return: BoxDriver
    """
    if not isinstance(driver_type, str):
        driver_type = 'c'

    driver_type = _parse_type(driver_type.lower())
    if wait_seconds:
        driver = BoxDriver(driver_type, wait_seconds=wait_seconds)
    else:
        driver = BoxDriver(driver_type)
    driver.navigate(url)
    driver.maximize_window()
    return driver


"""
main portal, for web api request
"""


def build_request(
        host,
        method,
        port=None):
    """
    get request for web api testing
    :param port: 主机端口号
    :param host: API 网址的 主机部分
    :param method: request method, str, 忽略大小写

    :return: BoxRequest
    """

    # method type: str, or default p
    if not isinstance(method, str):
        method = 'p'

    return BoxRequest(host=host,
                      method=_parse_method(method.lower()),
                      port=port)


"""
private method
"""


def build_logger(log_path):
    """
    build logger
    :param log_path:
    :return:
    """
    return Logger(
        log_path=log_path,
        call_path=__name__
    )


def _parse_type(driver_type):
    """
    parse driver type
    :param driver_type: str: driver type
        chrome: c or chrome
        firefox: f or firefox
        ie: i or ie
        safari: s or safari
        headless chrome: h or hc or headless, headless chrome
    :return: default value: BoxDriver.DriverType.CHROME
    """
    if driver_type == 'c' or driver_type == "chrome":
        return BoxDriver.DriverType.CHROME
    elif driver_type == 'f' or driver_type == "firefox":
        return BoxDriver.DriverType.FIREFOX
    elif driver_type == 'i' or driver_type == "ie":
        return BoxDriver.DriverType.IE
    elif driver_type == 's' or driver_type == "safari":
        return BoxDriver.DriverType.SAFARI
    elif driver_type == 'h' or driver_type == "headless" \
            or driver_type == "hc" or driver_type == "headless_chrome":
        return BoxDriver.DriverType.CHROME_HEADLESS

    return BoxDriver.DriverType.CHROME


def _parse_method(method):
    """
    parse request method
    :param method: str request method
        get: g or get
        post: p or post
        delete: d or delete
        put: u or put
        head: h or head
    :return: default value: POST
    """
    if method == 'g' or method == "get":
        return BoxRequest.RequestMethod.GET
    elif method == 'p' or method == "post":
        return BoxRequest.RequestMethod.POST
    elif method == 'd' or method == "delete":
        return BoxRequest.RequestMethod.DELETE
    elif method == 'u' or method == "put":
        return BoxRequest.RequestMethod.PUT
    elif method == 'h' or method == "head":
        return BoxRequest.RequestMethod.HEAD

    return BoxRequest.RequestMethod.POST


def read_csv(current_file_path, csv_to_current):
    """
    读取 Csv 文件，以便 基于 pytest 的参数化使用
    :param csv_to_current: 当前文件通过相对路径访问 csv 所需要的路径字符串
    :param current_file_path: 当前文件的绝对路径，请直接使用 __file__
    :return: csv_list[dict...]
    """
    csv_file = PathHelper.get_actual_path_by_current_file(current_file_path, csv_to_current)
    return CsvHelper.read_for_parametrize(csv_file)


def read_yaml(current_file_path, yml_to_current, key_of_page):
    """
    读取 Yml 文件，以便 Page 子类进行使用
    :param key_of_page:
    :param current_file_path:
    :param yml_to_current:
    :return:
    """
    yml_file = PathHelper.get_actual_path_by_current_file(current_file_path, yml_to_current)
    return YamlHelper.get_config_as_dict(yml_file, key_of_page)


def parse_json(json_dict, data_key, index=None, sub_key=None):
    """
    解析 JSON
    :param json_dict: 被解析的 JSON 的字典格式
    :param data_key:
    :param index:
    :param sub_key:
    :return:
    """
    if json_dict and isinstance(json_dict, dict):
        return JsonHelper.parse_json_dict_value(
            json_dict=json_dict,
            data_key=data_key,
            index=index,
            sub_key=sub_key
        )
    raise TypeError("请传递一个 json 转换的 dict 类型，作为 json_dict 来使用 parse_json()")


def get_sign(private_key):
    """
    根据 私钥 和 sha1 方法获取签名
    :param private_key:
    :return:
    """
    hm = hmac.new(key=bytes(private_key, 'utf-8'), digestmod=hashlib.sha1)
    if hm:
        return str(base64.b64encode(hm.digest()), 'utf-8')

    return None
